package com.zjw.zy.componse.demo.viewmodel

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import com.zjw.zy.componse.demo.base.BaseViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import java.util.concurrent.TimeUnit

/**
 * @author     ：zhong.jw
 * @date       ：Created in 2023/2/17 11:40
 * @description：
 */
class MineGameViewModel : BaseViewModel() {


    companion object {
        private const val TAG = "GameViewModel"

        const val ITEM_STATUS_UN_CLICK = -1
        const val ITEM_STATUS_BANG = -2
        const val ITEM_STATUS_FLAG = -3
        const val ITEM_STATUS_BLACK = 0

        const val DATA_SAFE = 0
        const val DATA_UNSAFE = 1

        const val RESULT_NONE = -2
        const val RESULT_SUCCESS = 0
        const val RESULT_FAILED = -1
    }


    private var mItemArray: Array<Array<MutableState<Int>>>? = null
    private var mDataArray: Array<IntArray>? = null

    private var timeChangeDisposable: Disposable? = null

    private var mHeight = 0
    private var mWidth = 0
    private var mSafeCount = 0
    private var mCurrentClickSafeCount = 0

    private val mTimeChange = mutableStateOf(0L)
    val timeChange: State<Long> by this::mTimeChange

    private val mResultChange = mutableStateOf(RESULT_NONE)
    val resultChange: State<Int> by this::mResultChange


    fun initGame(height: Int, width: Int) {
        mHeight = height
        mWidth = width
        mSafeCount = 0
        mCurrentClickSafeCount = 0
        mResultChange.value = RESULT_NONE

        mItemArray = Array(height) {
            Array(width) {
                mutableStateOf(ITEM_STATUS_UN_CLICK)
            }
        }

        //随机算法生成雷区
        mDataArray = Array(height) {
            IntArray(width) {
                val count = (1..5).random()
                if (count <= 1) {
                    //20%概率有雷
                    DATA_UNSAFE
                } else {
                    //记录无雷数量
                    mSafeCount++
                    DATA_SAFE
                }
            }
        }

        startTimeChange()
    }

    fun performClickItem(x: Int, y: Int, flag: Boolean = false) {
        //检查是否结束
        if (mResultChange.value != RESULT_NONE) {
            return
        }

        val old = mItemArray!![y][x].value

        //检查是否被点击
        if (old != ITEM_STATUS_UN_CLICK && old != ITEM_STATUS_FLAG) {
            return
        }
        //检查是否flag模式
        if (flag) {
            if (old == ITEM_STATUS_FLAG) {
                mItemArray!![y][x].value = ITEM_STATUS_UN_CLICK
            } else {
                mItemArray!![y][x].value = ITEM_STATUS_FLAG
            }
            return
        }

        //检查是否被标记flag
        if (old == ITEM_STATUS_FLAG) {
            return
        }


        if (isSafe(x, y)) {
            performNext(x, y)
        } else {
            //踩雷！！！
            //雷区展示
            showAllUnsafe()
            //游戏失败逻辑处理
            mResultChange.value = RESULT_FAILED
            stopTimeChange()
        }
    }

    private fun showAllUnsafe() {
        for (i in mDataArray!!.indices) {
            for (j in mDataArray!![i].indices) {
                if (!isSafe(j, i)) {
                    mItemArray!![i][j].value = ITEM_STATUS_BANG
                }
            }
        }
    }

    private fun performNext(x: Int, y: Int) {
        val count = findUnsafeCount(x, y)
        publishSafeClick(x, y, count)
        if (count == 0) {
            //左扩展
            performLeftNext(x, y)
            //上扩展
            performTopNext(x, y)
            //右扩展
            performRightNext(x, y)
            //下扩展
            performBottomNext(x, y)
        }

        //检查是否通关

    }

    private fun publishSafeClick(x: Int, y: Int, count: Int) {
        mCurrentClickSafeCount++
        mItemArray!![y][x].value = count

        if (mCurrentClickSafeCount == mSafeCount) {
            mResultChange.value = RESULT_SUCCESS

            showAllUnsafe()
            stopTimeChange()
        }
    }

    private fun performBottomNext(x: Int, y: Int) {
        if (y + 1 < mHeight && isUnClick(x, y + 1)) {
            val count = findUnsafeCount(x, y + 1)
            publishSafeClick(x, y + 1, count)
            if (count == 0) {
                performRightNext(x, y + 1)
                performLeftNext(x, y + 1)
                performBottomNext(x, y + 1)
            }
        }
    }

    private fun performRightNext(x: Int, y: Int) {
        if (x + 1 < mWidth && isUnClick(x + 1, y)) {
            val count = findUnsafeCount(x + 1, y)
            publishSafeClick(x + 1, y, count)
            if (count == 0) {
                performTopNext(x + 1, y)
                performRightNext(x + 1, y)
                performBottomNext(x + 1, y)
            }
        }

        if (x + 1 < mWidth && y - 1 >= 0 && isUnClick(x + 1, y - 1)) {
            val count = findUnsafeCount(x + 1, y - 1)
            publishSafeClick(x + 1, y - 1, count)
            if (count == 0) {
                performTopNext(x + 1, y - 1)
                performRightNext(x + 1, y - 1)
                performBottomNext(x + 1, y - 1)
            }
        }

        if (x + 1 < mWidth && y + 1 < mHeight && isUnClick(x + 1, y + 1)) {
            val count = findUnsafeCount(x + 1, y + 1)
            publishSafeClick(x + 1, y + 1, count)
            if (count == 0) {
                performTopNext(x + 1, y + 1)
                performRightNext(x + 1, y + 1)
                performBottomNext(x + 1, y + 1)
            }
        }
    }

    private fun performTopNext(x: Int, y: Int) {
        if (y - 1 >= 0 && isUnClick(x, y - 1)) {
            val count = findUnsafeCount(x, y - 1)
            publishSafeClick(x, y - 1, count)
            if (count == 0) {
                performTopNext(x, y - 1)
                performLeftNext(x, y - 1)
                performRightNext(x, y - 1)
            }
        }
    }

    private fun performLeftNext(x: Int, y: Int) {
        //正左
        if (x - 1 >= 0 && isUnClick(x - 1, y)) {
            val count = findUnsafeCount(x - 1, y)
            publishSafeClick(x - 1, y, count)
            if (count == 0) {
                performTopNext(x - 1, y)
                performLeftNext(x - 1, y)
                performBottomNext(x - 1, y)
            }
        }

        //左上
        if (x - 1 >= 0 && y - 1 >= 0 && isUnClick(x - 1, y - 1)) {
            val count = findUnsafeCount(x - 1, y - 1)
            publishSafeClick(x - 1, y - 1, count)
            if (count == 0) {
                performTopNext(x - 1, y - 1)
                performLeftNext(x - 1, y - 1)
                performBottomNext(x - 1, y - 1)
            }
        }

        //左下
        if (x - 1 >= 0 && y + 1 < mHeight && isUnClick(x - 1, y + 1)) {
            val count = findUnsafeCount(x - 1, y + 1)
            publishSafeClick(x - 1, y + 1, count)
            if (count == 0) {
                performTopNext(x - 1, y + 1)
                performLeftNext(x - 1, y + 1)
                performBottomNext(x - 1, y + 1)
            }
        }

    }

    private fun isSafe(x: Int, y: Int): Boolean {
        return mDataArray!![y][x] == DATA_SAFE
    }

    /**
     * 未点击
     * */
    private fun isUnClick(x: Int, y: Int): Boolean {
        return mItemArray!![y][x].value == ITEM_STATUS_UN_CLICK
    }

    private fun findUnsafeCount(x: Int, y: Int): Int {

        var count = 0
        if (x - 1 >= 0 && !isSafe(x - 1, y)) {
            count++
        }
        if (x + 1 < mWidth && !isSafe(x + 1, y)) {
            count++
        }
        if (y - 1 >= 0 && !isSafe(x, y - 1)) {
            count++
        }
        if (y + 1 < mHeight && !isSafe(x, y + 1)) {
            count++
        }
        if (x - 1 >= 0 && y - 1 >= 0 && !isSafe(x - 1, y - 1)) {
            count++
        }

        if (x - 1 >= 0 && y + 1 < mHeight && !isSafe(x - 1, y + 1)) {
            count++
        }

        if (x + 1 < mWidth && y - 1 >= 0 && !isSafe(x + 1, y - 1)) {
            count++
        }

        if (x + 1 < mWidth && y + 1 < mHeight && !isSafe(x + 1, y + 1)) {
            count++
        }

        return count
    }

    fun observeItem(x: Int, y: Int): State<Int> {
        return mItemArray!![y][x]
    }

    private fun startTimeChange() {
        timeChangeDisposable?.dispose()
        timeChangeDisposable =
            Observable.interval(1, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    mTimeChange.value = it
                }
    }

    private fun stopTimeChange() {
        timeChangeDisposable?.dispose()

        //记录
    }
}